package com.lyf.shop.service.impl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.lyf.shop.constant.CartConstant;
import com.lyf.shop.constant.LoginConstant;
import com.lyf.shop.entity.Car;
import com.lyf.shop.dao.CarDao;
import com.lyf.shop.entity.Product;
import com.lyf.shop.entity.User;
import com.lyf.shop.service.CarService;
import com.lyf.shop.service.ProductService;
import com.lyf.shop.vo.CartItemVo;
import com.lyf.shop.vo.CartVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.List;

/**
 * (Car)表服务实现类
 *
 * @author makejava
 * @since 2021-12-03 14:45:41
 */
@Service("carService")
public class CarServiceImpl implements CarService {
    @Resource
    private CarDao carDao;
    @Autowired
    HttpSession httpSession;
    @Autowired
    StringRedisTemplate redisTemplate;
    @Autowired
    ObjectMapper objectMapper;
    @Autowired
    ProductService productService;

    /**
     * 通过ID查询单条数据
     *
     * @param cid 主键
     * @return 实例对象
     */
    @Override
    public Car queryById(Integer cid) {
        return this.carDao.queryById(cid);
    }

    /**
     * 查询多条数据
     *
     * @param offset 查询起始位置
     * @param limit  查询条数
     * @return 对象列表
     */
    @Override
    public List<Car> queryAllByLimit(int offset, int limit) {
        return this.carDao.queryAllByLimit(offset, limit);
    }

    /**
     * 新增数据
     *
     * @param car 实例对象
     * @return 实例对象
     */
    @Override
    public Car insert(Car car) {
        this.carDao.insert(car);
        return car;
    }

    /**
     * 修改数据
     *
     * @param car 实例对象
     * @return 实例对象
     */
    @Override
    public Car update(Car car) {
        this.carDao.update(car);
        return this.queryById(car.getCid());
    }

    /**
     * 通过主键删除数据
     *
     * @param cid 主键
     * @return 是否成功
     */
    @Override
    public boolean deleteById(Integer cid) {
        return this.carDao.deleteById(cid) > 0;
    }

    @Override
    public CartVo getCart() throws JsonProcessingException {
        // 连接redis，获取函数，拿到这个引用
        BoundHashOperations<String, String, String> hashOps = getRedisHashOps();
        // 从redis获取key为cart的数据
        String cart = hashOps.get(CartConstant.CART_CACHE_KEY);
        CartVo cartVo = null;
        if (cart == null) {
            //创建购物车
            cartVo = new CartVo();
            ArrayList<CartItemVo> cartItemVos = new ArrayList<>();
            cartVo.setCartItems(cartItemVos);
            String cartJson = objectMapper.writeValueAsString(cartVo);
            // 存入redis
            hashOps.put(CartConstant.CART_CACHE_KEY, cartJson);
        } else {
            cartVo = objectMapper.readValue(cart, CartVo.class);
        }
        return cartVo;
    }

    private BoundHashOperations<String, String, String> getRedisHashOps() {
        User user = (User) httpSession.getAttribute(LoginConstant.LOGIN_USER_KEY);
        Integer uid = user.getUid();
        //绑定操作
        String key = CartConstant.CART_CACHE_HASH_KEY + uid;
        BoundHashOperations<String, String, String> hashOps = redisTemplate.boundHashOps(key);
        //hashOps作为一个引用指向当前用户属于的购物车
        return hashOps;
    }

    @Override
    public void addCartItem(CartVo cartVo, int pid, int num) throws JsonProcessingException {
        Product product = productService.queryById(pid);
        if (product != null) {
            //查看购物车里是否已有该商品
            List<CartItemVo> cartItems = cartVo.getCartItems();
            for (CartItemVo cartItem : cartItems) {
                if (cartItem.getPid().equals(product.getPid())) {
                    cartItem.setCount(cartItem.getCount() + num);
                    updateCart(cartVo);
                    return;
                }
            }
            //是新增类型商品
            CartItemVo cartItemVo = new CartItemVo();
            BeanUtils.copyProperties(product, cartItemVo);
            cartItemVo.setCount(num);
            cartItemVo.setChecked(true);
            cartVo.addCartItems(cartItemVo);
            //更新购物车
            updateCart(cartVo);
        }
    }

    @Override
    public void deleteCartItem(CartVo cart, int pid) throws JsonProcessingException {
        List<CartItemVo> cartItems = cart.getCartItems();
        boolean removeIf = cartItems.removeIf((item) -> item.getPid().equals(pid));
        if (removeIf) {
            updateCart(cart);
        }
    }

    @Override
    public void changeChecked(CartVo cart, int pid) throws JsonProcessingException {
        List<CartItemVo> cartItems = cart.getCartItems();
        for (CartItemVo cartItem : cartItems) {
            if (cartItem.getPid().equals(pid)) {
                cartItem.setChecked(!cartItem.isChecked());
                updateCart(cart);
                return;
            }
        }
    }

    @Override
    public void changeCartItemNum(CartVo cart, int pid, int num) throws JsonProcessingException {
        List<CartItemVo> cartItems = cart.getCartItems();
        for (CartItemVo cartItem : cartItems) {
            if (cartItem.getPid().equals(pid)) {
                cartItem.setCount(num);
                updateCart(cart);
                return;
            }
        }
    }

    private void updateCart(CartVo cartVo) throws JsonProcessingException {
        // 更新redis数据
        String json = objectMapper.writeValueAsString(cartVo);
        BoundHashOperations<String, String, String> hashOps = getRedisHashOps();
        hashOps.put(CartConstant.CART_CACHE_KEY, json);
    }
}